package it.softphone.cmc.server.config;

import it.softphone.cmc.server.service.TaskQueueService;
import it.softphone.cmc.server.service.TenantService;
import it.softphone.cmc.server.service.exception.CMCException;
import it.softphone.cmc.server.service.impl.GAETaskQueueServiceImpl;
import it.softphone.cmc.server.service.impl.GAETenantServiceImpl;
import it.softphone.commons.spring.ApplicationConfig;
import it.softphone.commons.spring.config.BaseConfigSupport;

import java.util.HashMap;
import java.util.Map;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheFactory;
import javax.cache.CacheListener;
import javax.cache.CacheManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.servlet.ServletContext;

import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.springframework.config.java.annotation.Bean;
import org.springframework.config.java.annotation.Configuration;
import org.springframework.config.java.annotation.Lazy;
import org.springframework.config.java.plugin.context.AnnotationDrivenConfig;
import org.springframework.config.java.plugin.context.ComponentScan;

import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.stdimpl.GCacheFactory;
import com.newatlanta.commons.vfs.provider.gae.GaeVFS;

@Configuration
@AnnotationDrivenConfig
@ComponentScan("it.softphone.cmc.server.service.impl")
public class GAEConfig extends BaseConfigSupport {
	
	@Bean public EntityManagerFactory entityManagerFactory() {
		return Persistence.createEntityManagerFactory("cmc-persistent-unit");
	}

	@Bean(lazy=Lazy.FALSE) public TenantService tenantService() {
		
		TenantService result = new GAETenantServiceImpl();
		
		return result;
				
	}

	/**
	 * 
	 * @return
	 */
	@Bean public FileSystemManager vfs() {
		String path = null;
		
		try {
			ServletContext ctx = ApplicationConfig.getServletContext();
			if( ctx == null ) {
				final String message = "ServletContext is null!";
				throw new IllegalStateException(message);
			}
			path = ctx.getRealPath("WEB-INF") ;
		}
		catch( Throwable ex ) {
			logger.warn( String.format("error reading root path [%s]", ex.getMessage() ));

			path = System.getProperty("java.io.tmpdir");
			
		}
		logger.info( String.format("VFS root path [%s]", path ));
		GaeVFS.setRootPath( path );
		
		try {
			
			return GaeVFS.getManager();
			
		} catch (FileSystemException e) {
			
			logger.error( "error initializing Virtual File System ");
			
			throw new RuntimeException(e);
		}
		
	}
	
	/**
	 * GAE CHANNEL SERVICE
	 * 
	 * @return
	 */
	/*
	@Bean(lazy=Lazy.FALSE) public EventManagerService eventService() {
		
		EventManagerService event = new GAEEventManagerServiceImpl();
		
		return event;
				
	}
	*/
	
	@Bean(lazy=Lazy.TRUE) public TaskQueueService taskQueueService () {
		
		return new GAETaskQueueServiceImpl();
				
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Bean 
	public javax.cache.Cache registrationCache() throws CMCException {
       
		Cache cache = null;
		
		Map props = new HashMap();
        props.put(GCacheFactory.EXPIRATION_DELTA, 3600); // IN SECONDS
        props.put(MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT, true);
        try {
            CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
            cache = cacheFactory.createCache(props);
            cache.addListener( new CacheListener() {
				
				@Override
				public void onRmove(Object key) {
					logger.debug( String.format("onRemove( %s )", key ) );
				}
				
				@Override
				public void onPut(Object key) {
					logger.debug( String.format("onPut( %s )", key ) );					
				}
				
				@Override
				public void onLoad(Object key) {
					logger.debug( String.format("onLoad( %s )", key ) );					
				}
				
				@Override
				public void onEvict(Object key) {
					logger.debug( String.format("onEvict( %s )", key ) );					
				}
				
				@Override
				public void onClear() {
					logger.debug( "onClear()" );					
				}
			});
        } catch (CacheException e) {
            throw new CMCException("getting registrationCache fail!", e); 
        }        
        
        return cache;
	}
	
	/**
	 * 
	 * @return
	 */
	@Bean(lazy=Lazy.TRUE) 
	public javax.mail.Session mailService() {
		
        java.util.Properties props = new java.util.Properties();
        javax.mail.Session session = javax.mail.Session.getDefaultInstance(props, null);
        
        
        return session;	

	}
}
